unit uGoogleMap;

interface

uses
  SysUtils, Classes, uDZSysUtils, uDZWinInetUtils, uGxtCity;

type
  TGoogleMapPlaceMark = record
    Address: WideString;
    CountryCode: WideString;
    CountryName: WideString;
    AdministrativeAreaName: WideString;
    LocalityName: WideString;
    DependentLocalityName: WideString;
    ThoroughfareName: WideString;
  end;

  TGoogleMap = class
  private
    fHttpClient: TDzWinInetHttp;
  public
    constructor Create;
    destructor Destroy; override;
    function GetPlaceNameFromCoord(const lat, lng: string): WideString;
    function GetPlaceMarkFromCoord(const lat, lng: string;
      var pm: TGoogleMapPlaceMark): Boolean;
  end;

function GetPlaceNameFromCoord(const lat, lng: string): WideString;
function GetPlaceMarkFromCoord(const lat, lng: string;
  var pm: TGoogleMapPlaceMark): Boolean;
procedure QueryPlace(x, y: AnsiString; out CityID: Integer;
  out ProvinceName, CityName, Address: WideString);

implementation

uses
  uDZStr, uDZXML;

const
  GOOGLE_MAP_URI = 'http://ditu.google.cn/maps/geo?output=xml&oe=utf-8&ll=%s%%2C%s&hl=cn';

procedure QueryPlace(x, y: AnsiString; out CityID: Integer;
  out ProvinceName, CityName, Address: WideString);
const
  PROVINCE_CHAR: WideChar = #30465;
  CITY_CHAR: WideChar = #24066;   
var
  pm: TGoogleMapPlaceMark;
  City: uGxtCity.TCity;
  procedure DeleteTitle(var src: WideString; tc: WideChar);
  begin
    if src = '' then Exit;
    if src[Length(src)] = tc then SetLength(src, Length(src) - 1);
  end;
begin
  with AreaList do
  begin
    if GetPlaceMarkFromCoord(x, y, pm) then
    begin
      DeleteTitle(pm.AdministrativeAreaName, PROVINCE_CHAR);
      DeleteTitle(pm.LocalityName, CITY_CHAR);
      pm.LocalityName := GetCnCityName(pm.LocalityName);
      ProvinceName := GetCnProvinceName(pm.AdministrativeAreaName);
      CityName := GetCnCityName(pm.LocalityName);
      Address := pm.Address;
      City := GetCityByName(pm.LocalityName);
      if City <> nil then CityID := city.ID;
    end;
  end;
end;

function GetPlaceNameFromCoord(const lat, lng: string): WideString;
var
  gissvc: TGoogleMap;
begin
  gissvc := TGoogleMap.Create;
  try
    Result := gissvc.GetPlaceNameFromCoord(lat, lng);
  finally
    gissvc.Free;
  end;
end;

function GetPlaceMarkFromCoord(const lat, lng: string;
  var pm: TGoogleMapPlaceMark): Boolean;
var
  gissvc: TGoogleMap;
begin
  gissvc := TGoogleMap.Create;
  try
    Result := gissvc.GetPlaceMarkFromCoord(lat, lng, pm);
  finally
    gissvc.Free;
  end;
end;

{ TGoogleMap }

constructor TGoogleMap.Create;
begin
  fHttpClient := TDzWinInetHttp.Create;
end;

destructor TGoogleMap.Destroy;
begin
  fHttpClient.Free;
  inherited;
end;

function TGoogleMap.GetPlaceMarkFromCoord(const lat, lng: string;
  var pm: TGoogleMapPlaceMark): Boolean;
var
  xml, value: UTF8String;
  procedure GetNodeText(const Name: AnsiString; out Text: WideString);
  begin
    if XMLGetInnerXMLA(xml, Name, AnsiString(value)) then Text := UTF8Decode(value)
    else Text := '';
  end;
begin
  Result := False;
  try
    xml := HttpGet(fHttpClient, Format(GOOGLE_MAP_URI, [lat, lng]));
    if (not XMLGetInnerXMLA(xml, 'code', AnsiString(value)) or (value <> '200')) then Exit;
    GetNodeText('address', pm.Address);
    GetNodeText('CountryNameCode', pm.CountryCode);
    GetNodeText('CountryName', pm.CountryName);
    GetNodeText('AdministrativeAreaName', pm.AdministrativeAreaName);
    GetNodeText('LocalityName', pm.LocalityName);
    GetNodeText('ThoroughfareName', pm.ThoroughfareName);
    Result := True;
  except

  end;
end;

function TGoogleMap.GetPlaceNameFromCoord(const lat, lng: string): WideString;
var
  xml, text: UTF8String;
begin
  Result := '';
  try
    xml := HttpGet(fHttpClient, Format(GOOGLE_MAP_URI, [lat, lng]));
    if XMLGetInnerXMLA(xml, 'address', AnsiString(text)) then
      Result := Utf8Decode(text);
  except

  end;
end;

end.
